Esse material foca principalmente no uso do pacote dplyr, porém será carregado o pacote tidyverse, que contém diversos outros pacotes inclusos, entre eles o dplyre o ggplot2.
#install.packages("tidyverse")
library(tidyverse)O banco de dados utilizado é um exemplo de parcelas de inventário florestal, onde foram obtidas, entre outras variáveis, o nome científico da espécie, o CAP, altura comercial e altura total.
setwd("/home/orso/OneDrive/Florestal/Outros/dplyr")
dados <- read.csv2("dados.csv", h = T)
str(dados)## 'data.frame': 764 obs. of 13 variables:
## $ par : int 3 3 3 3 3 3 3 3 3 3 ...
## $ ind : int 1 2 3 4 5 6 7 8 8 9 ...
## $ fam : chr "Euphorbiaceae" "Meliaceae" "Lauraceae" "Elaeocarpaceae" ...
## $ cient : chr "Alchornea triplinervia" "Guarea macrophylla" "Ocotea dispersa" "Sloanea guianensis" ...
## $ autor : chr "(Spreng.) M\xfcll.Arg." "Vahl" "(Nees & Mart.) Mez" "(Aubl.) Benth." ...
## $ verna : chr "Tanheiro" "Caf\xe9-bravo" "Canela-sab\xe3o" "Urucurana" ...
## $ cap : num 82 18 20 57 70 17 44 33 31 17 ...
## $ ht : num 17 5.5 6 10 12 8 12 10 10 6 ...
## $ hc : num 6 3 4 7 7 3 7 6 6 3 ...
## $ qf : int 2 1 2 3 3 3 3 2 2 3 ...
## $ qc : int 1 1 1 2 2 3 2 1 1 3 ...
## $ estrato: chr "dossel" "sub" "sub" "inter" ...
## $ obs : chr "" "" "" "" ...
O pacote dplyr é um conjunto de ferramentas para manipulação de bancos de dados, e fornece alternativas rápidas e intuitivas para resolver as principais demandas de análise, manipulação e resumo dos dados.
Tomando-se como exemplo um inventário florestal, deseja-se obter a partir dos dados brutos, um resumo do número de indivíduos, diâmetro médio e área basal por parcela.
# Calcular DAP e área transversal
dados$dap <- dados$cap/pi
dados$g <- (dados$dap**2*pi)/40000
# Calcular número de indivíduos
n.ind <- table(dados$par)
# Calcular o DAP médio e a área basal da parcela
dap.m <- tapply(X = dados$dap, INDEX = dados$par, FUN = mean, na.rm=T)
G <- tapply(X = dados$g, INDEX = dados$par, FUN = sum, na.rm=T)
resumo.base <- data.frame(n.ind, dap.m, G)
resumo.base## Var1 Freq dap.m G
## 3 3 48 13.37565 1.2880211
## 6 6 36 16.49022 1.2675975
## 7 7 50 11.68002 0.7185567
## 8 8 53 12.02371 0.7833129
## 9 9 49 13.69707 0.8875057
## 10 10 39 14.23008 0.9500854
## 11 11 62 12.64512 0.9436257
## 12 12 37 13.39052 0.7791371
## 13 13 22 21.13867 1.0729828
## 14 14 38 17.55730 1.3661065
## 15 15 42 14.77867 1.1987550
## 16 16 30 16.43010 0.8968162
## 17 17 42 15.10456 1.1259496
## 18 18 37 14.69387 0.8780618
## 19 19 46 16.23034 1.4723444
## 20 20 29 19.07664 1.7538238
## 21 21 50 12.45228 1.1429553
## 22 22 54 14.33279 1.5268907
dplyrdados %>%
mutate(dap = cap/pi, g = (dap^2*pi)/40000) %>%
group_by(par) %>%
summarise(n.ind = n(), dap.m = mean(dap, na.rm=T), G = sum(g, na.rm=T))## # A tibble: 18 x 4
## par n.ind dap.m G
## <int> <int> <dbl> <dbl>
## 1 3 48 13.4 1.29
## 2 6 36 16.5 1.27
## 3 7 50 11.7 0.719
## 4 8 53 12.0 0.783
## 5 9 49 13.7 0.888
## 6 10 39 14.2 0.950
## 7 11 62 12.6 0.944
## 8 12 37 13.4 0.779
## 9 13 22 21.1 1.07
## 10 14 38 17.6 1.37
## 11 15 42 14.8 1.20
## 12 16 30 16.4 0.897
## 13 17 42 15.1 1.13
## 14 18 37 14.7 0.878
## 15 19 46 16.2 1.47
## 16 20 29 19.1 1.75
## 17 21 50 12.5 1.14
## 18 22 54 14.3 1.53
Colocando mais uma vez o código utilizado, agora mais desmembrado e explicado, é possível perceber que todos os comandos estão conectados por um operador %>%, chamado pipe. Esse operador é similar ao operador “+” utilizado para conectar os comandos do ggplot2, e sua principal vantagem é que diversas operações podem ser realizadas sem a necessidade de criar e armazenar novos objetos, tornando o script mais rápido e fluido.
resumo.dplyr <- dados %>%
mutate(dap = cap/pi, # mutate cria novas colunas no data frame
g = (dap^2*pi)/40000) %>%
group_by(par) %>% # group_by agrupa os dados com base na variável informada
summarise(n.ind = n(), # summarise resume as informações
dap.m = mean(dap, na.rm=T),
G = sum(g, na.rm=T))
resumo.dplyrNo exemplo acima, mutate() cria novas colunas no data frame; group_by() agrupa os dados com base na coluna desejada, e summarise() resume os grupos com base na função informada (n(), mean() e sum()).
%>%Os pipes %>% são operadores muito utilizados no pacote dplyr. Eles permitem encadear sequências de comandos, de forma similar ao operador “+” no pacote ggplot2.
De forma resumida, o operador pega tudo que está à esquerda, e joga como primeiro argumento na função que está à sua direita.
#Selecionar as primeiras 10 linhas do data frame
df <- dados[1:10, ]
#Selecionar apenas as colunas "cient", "cap" e "ht"
select(df, cient, cap, ht)## cient cap ht
## 1 Alchornea triplinervia 82 17.0
## 2 Guarea macrophylla 18 5.5
## 3 Ocotea dispersa 20 6.0
## 4 Sloanea guianensis 57 10.0
## 5 Ilex dumosa 70 12.0
## 6 Myrcia reitzii 17 8.0
## 7 Calophyllum brasiliense 44 12.0
## 8 Sloanea guianensis 33 10.0
## 9 Sloanea guianensis 31 10.0
## 10 Myrcia racemosa 17 6.0
#Selecionar apenas as colunas "cient", "cap" e "ht"
df %>% select(cient, cap, ht)## cient cap ht
## 1 Alchornea triplinervia 82 17.0
## 2 Guarea macrophylla 18 5.5
## 3 Ocotea dispersa 20 6.0
## 4 Sloanea guianensis 57 10.0
## 5 Ilex dumosa 70 12.0
## 6 Myrcia reitzii 17 8.0
## 7 Calophyllum brasiliense 44 12.0
## 8 Sloanea guianensis 33 10.0
## 9 Sloanea guianensis 31 10.0
## 10 Myrcia racemosa 17 6.0
Essa lógica se mantém para o uso de mais comandos em sequência, lembrando que o operador pega tudo que está à esquerda e insere como primeiro argumento no comando à direita.
df %>% select(cient, cap, ht) %>% mutate(dap = cap/pi)## cient cap ht dap
## 1 Alchornea triplinervia 82 17.0 26.101411
## 2 Guarea macrophylla 18 5.5 5.729578
## 3 Ocotea dispersa 20 6.0 6.366198
## 4 Sloanea guianensis 57 10.0 18.143664
## 5 Ilex dumosa 70 12.0 22.281692
## 6 Myrcia reitzii 17 8.0 5.411268
## 7 Calophyllum brasiliense 44 12.0 14.005635
## 8 Sloanea guianensis 33 10.0 10.504226
## 9 Sloanea guianensis 31 10.0 9.867606
## 10 Myrcia racemosa 17 6.0 5.411268
df %>% select(cient, ht) %>% mutate(dap = cap/pi)## Error: Problem with `mutate()` input `dap`.
## x objeto 'cap' não encontrado
## i Input `dap` is `cap/pi`.
Esse último exemplo resultou em um erro pois a variável “cap” não foi selecionada, e como consequência não há como calcular a nova variável “dap”. O segundo operador %>% recebe um data frame contendo apenas as variáveis “cient” e “ht”, e insere esse data frame no início do comando mutate(). O erro surge por não existir a variável “dap” no data frame fornecido.
Pipes
filter()A função filter() é utilizada para filtrar linhas que satisfaçam uma determinada condição.
dados <- as_tibble(dados)
dados %>% filter(par == 6)## # A tibble: 36 x 15
## par ind fam cient autor verna cap ht hc qf qc estrato
## <int> <int> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <int> <int> <chr>
## 1 6 1 Euph~ Alch~ (Spr~ Tanh~ 63 11 6 1 2 dossel
## 2 6 2 Bign~ Jaca~ Cham. Caro~ 28 5 3 2 1 sub
## 3 6 3 Prim~ Myrs~ (Sw.~ Capo~ 27 9 5 1 1 dossel
## 4 6 4 Euph~ Alch~ (Spr~ Tanh~ 21 7 5 1 2 inter
## 5 6 5 Mela~ Pler~ DC. Jaca~ 21 7 4.5 1 1 inter
## 6 6 6 Laur~ Ocot~ Mez Cane~ 70 12 1 3 1 dossel
## 7 6 6 Laur~ Ocot~ Mez Cane~ 67 12 1 3 1 dossel
## 8 6 7 Meli~ Guar~ Vahl Café~ 18 6 2 3 1 sub
## 9 6 8 Calo~ Calo~ Camb~ Guan~ 212 17 8 1 1 dossel
## 10 6 9 Myrt~ Myrc~ Kiae~ Camb~ 25 6 2 2 2 dub
## # ... with 26 more rows, and 3 more variables: obs <chr>, dap <dbl>, g <dbl>
dados %>% filter(cap >= 140)## # A tibble: 23 x 15
## par ind fam cient autor verna cap ht hc qf qc estrato
## <int> <int> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <int> <int> <chr>
## 1 3 21 "Cal~ Calo~ "Cam~ "Gua~ 199 25 10 1 1 "emerg"
## 2 3 29 "Cal~ Calo~ "Cam~ "Gua~ 200 24 8 1 1 "emerg"
## 3 6 8 "Cal~ Calo~ "Cam~ "Gua~ 212 17 8 1 1 "dosse~
## 4 6 13 "Cal~ Calo~ "Cam~ "Gua~ 141 17 12 1 1 "dosse~
## 5 10 22 "Lau~ Nect~ "Nee~ "Can~ 148 17 10 2 3 "dosse~
## 6 10 25 "" Morta "" "" 142 NA NA NA NA ""
## 7 12 11 "Sap~ Mata~ "Rad~ "Mat~ 163 16 2 2 1 "dosse~
## 8 13 22 "Cal~ Calo~ "Cam~ "Gua~ 229 17 10 1 1 "emerg"
## 9 14 4 "Eup~ Alch~ "(Sp~ "Tan~ 165 19 7 2 1 "emerg"
## 10 14 19 "Eup~ Alch~ "(Sp~ "Tan~ 141 20 7 2 1 "emerg"
## # ... with 13 more rows, and 3 more variables: obs <chr>, dap <dbl>, g <dbl>
dados %>% filter(cap >= 140 & par == 10)## # A tibble: 2 x 15
## par ind fam cient autor verna cap ht hc qf qc estrato
## <int> <int> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <int> <int> <chr>
## 1 10 22 "Lau~ Nect~ "Nee~ "Can~ 148 17 10 2 3 "dosse~
## 2 10 25 "" Morta "" "" 142 NA NA NA NA ""
## # ... with 3 more variables: obs <chr>, dap <dbl>, g <dbl>
df <- dados %>% filter(cap >= 140)Filter
print(df)## # A tibble: 23 x 15
## par ind fam cient autor verna cap ht hc qf qc estrato
## <int> <int> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <int> <int> <chr>
## 1 3 21 "Cal~ Calo~ "Cam~ "Gua~ 199 25 10 1 1 "emerg"
## 2 3 29 "Cal~ Calo~ "Cam~ "Gua~ 200 24 8 1 1 "emerg"
## 3 6 8 "Cal~ Calo~ "Cam~ "Gua~ 212 17 8 1 1 "dosse~
## 4 6 13 "Cal~ Calo~ "Cam~ "Gua~ 141 17 12 1 1 "dosse~
## 5 10 22 "Lau~ Nect~ "Nee~ "Can~ 148 17 10 2 3 "dosse~
## 6 10 25 "" Morta "" "" 142 NA NA NA NA ""
## 7 12 11 "Sap~ Mata~ "Rad~ "Mat~ 163 16 2 2 1 "dosse~
## 8 13 22 "Cal~ Calo~ "Cam~ "Gua~ 229 17 10 1 1 "emerg"
## 9 14 4 "Eup~ Alch~ "(Sp~ "Tan~ 165 19 7 2 1 "emerg"
## 10 14 19 "Eup~ Alch~ "(Sp~ "Tan~ 141 20 7 2 1 "emerg"
## # ... with 13 more rows, and 3 more variables: obs <chr>, dap <dbl>, g <dbl>
df %>% filter(cap >= 200 | cient == 'Matayba intermedia')## # A tibble: 8 x 15
## par ind fam cient autor verna cap ht hc qf qc estrato
## <int> <int> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <int> <int> <chr>
## 1 3 29 Calo~ Calo~ "Cam~ "Gua~ 200 24 8 1 1 emerg
## 2 6 8 Calo~ Calo~ "Cam~ "Gua~ 212 17 8 1 1 dossel
## 3 12 11 Sapi~ Mata~ "Rad~ "Mat~ 163 16 2 2 1 dossel
## 4 13 22 Calo~ Calo~ "Cam~ "Gua~ 229 17 10 1 1 emerg
## 5 16 5 Sapi~ Mata~ "Rad~ "Mat~ 150 15 8 2 1 emerg
## 6 20 8 Sapo~ Mani~ "(Ma~ "Maç~ 338 30 20 1 1 e
## 7 21 9 Faba~ Pter~ "Vah~ "Pau~ 230 25 6 2 1 dossel
## 8 22 17 Inde~ Inde~ "" "" 228 23 10 2 1 dossel
## # ... with 3 more variables: obs <chr>, dap <dbl>, g <dbl>
Filter Ou
df %>% filter(dap > 50 & ht >= 20)## # A tibble: 6 x 15
## par ind fam cient autor verna cap ht hc qf qc estrato
## <int> <int> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <int> <int> <chr>
## 1 3 21 Calo~ Calo~ "Cam~ "Gua~ 199 25 10 1 1 emerg
## 2 3 29 Calo~ Calo~ "Cam~ "Gua~ 200 24 8 1 1 emerg
## 3 20 8 Sapo~ Mani~ "(Ma~ "Maç~ 338 30 20 1 1 e
## 4 20 25 Faba~ Pter~ "Vah~ "Pau~ 163 26 10 1 1 dossel
## 5 21 9 Faba~ Pter~ "Vah~ "Pau~ 230 25 6 2 1 dossel
## 6 22 17 Inde~ Inde~ "" "" 228 23 10 2 1 dossel
## # ... with 3 more variables: obs <chr>, dap <dbl>, g <dbl>
Filter E
select()A função select() é utilizada para selecionar colunas.
dados %>% select(cap, ht)## # A tibble: 764 x 2
## cap ht
## <dbl> <dbl>
## 1 82 17
## 2 18 5.5
## 3 20 6
## 4 57 10
## 5 70 12
## 6 17 8
## 7 44 12
## 8 33 10
## 9 31 10
## 10 17 6
## # ... with 754 more rows
Select
dados %>% select(-par)## # A tibble: 764 x 14
## ind fam cient autor verna cap ht hc qf qc estrato obs
## <int> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <int> <int> <chr> <chr>
## 1 1 Euph~ Alch~ (Spr~ Tanh~ 82 17 6 2 1 dossel ""
## 2 2 Meli~ Guar~ Vahl Café~ 18 5.5 3 1 1 sub ""
## 3 3 Laur~ Ocot~ (Nee~ Cane~ 20 6 4 2 1 sub ""
## 4 4 Elae~ Sloa~ (Aub~ Uruc~ 57 10 7 3 2 inter ""
## 5 5 Aqui~ Ilex~ Reis~ Caúna 70 12 7 3 2 dossel ""
## 6 6 Myrt~ Myrc~ (D.L~ Camb~ 17 8 3 3 3 sub ""
## 7 7 Calo~ Calo~ Camb~ Guan~ 44 12 7 3 2 inter ""
## 8 8 Elae~ Sloa~ (Aub~ Uruc~ 33 10 6 2 1 inter "bif"
## 9 8 Elae~ Sloa~ (Aub~ Uruc~ 31 10 6 2 1 inter "bif"
## 10 9 Myrt~ Myrc~ (O.B~ Guam~ 17 6 3 3 3 sub "bif"
## # ... with 754 more rows, and 2 more variables: dap <dbl>, g <dbl>
dados %>% select(-c(par, fam, cient, autor, verna))## # A tibble: 764 x 10
## ind cap ht hc qf qc estrato obs dap g
## <int> <dbl> <dbl> <dbl> <int> <int> <chr> <chr> <dbl> <dbl>
## 1 1 82 17 6 2 1 dossel "" 26.1 0.0535
## 2 2 18 5.5 3 1 1 sub "" 5.73 0.00258
## 3 3 20 6 4 2 1 sub "" 6.37 0.00318
## 4 4 57 10 7 3 2 inter "" 18.1 0.0259
## 5 5 70 12 7 3 2 dossel "" 22.3 0.0390
## 6 6 17 8 3 3 3 sub "" 5.41 0.00230
## 7 7 44 12 7 3 2 inter "" 14.0 0.0154
## 8 8 33 10 6 2 1 inter "bif" 10.5 0.00867
## 9 8 31 10 6 2 1 inter "bif" 9.87 0.00765
## 10 9 17 6 3 3 3 sub "bif" 5.41 0.00230
## # ... with 754 more rows
Select Inverso
mutate()A função mutate() permite criar e adicionar novas variáveis no dataframe, utilizando tanto variáveis externas quanto do próprio dataframe.
# Carregando novamente os dados para criar variáveis
dados <- read.csv2('dados.csv')
# Criando as variáveis dap e g
dados <- dados %>% mutate(dap = cap/pi,
g = dap^2*pi/40000)
head(dados %>% select(dap, g))## dap g
## 1 26.101411 0.053507892
## 2 5.729578 0.002578310
## 3 6.366198 0.003183099
## 4 18.143664 0.025854721
## 5 22.281692 0.038992961
## 6 5.411268 0.002299789
Note que, para esse caso, a variável g fez uso da variável dap recém criada. Esse recurso “on the fly” é oportuno para criar de forma encadeada diversas variáveis de maneira simples e rápida. Além disso, também fica claro que há uma ordem de criação das variáveis.
Mutate
group_by()A função group_by() agrupa o data frame com base em uma variável especificada. A função não faz alterações no dataframe, apenas marca internamente os grupos para que alguma outra função seja realizada em cima desses grupos marcados.
# Data frame antes da operação group_by()
head(tibble(dados))## # A tibble: 6 x 15
## par ind fam cient autor verna cap ht hc qf qc estrato
## <int> <int> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <int> <int> <chr>
## 1 3 1 Euph~ Alch~ (Spr~ Tanh~ 82 17 6 2 1 dossel
## 2 3 2 Meli~ Guar~ Vahl Café~ 18 5.5 3 1 1 sub
## 3 3 3 Laur~ Ocot~ (Nee~ Cane~ 20 6 4 2 1 sub
## 4 3 4 Elae~ Sloa~ (Aub~ Uruc~ 57 10 7 3 2 inter
## 5 3 5 Aqui~ Ilex~ Reis~ Caúna 70 12 7 3 2 dossel
## 6 3 6 Myrt~ Myrc~ (D.L~ Camb~ 17 8 3 3 3 sub
## # ... with 3 more variables: obs <chr>, dap <dbl>, g <dbl>
# Data frame após a operação group_by()
head(dados %>% group_by(par))## # A tibble: 6 x 15
## # Groups: par [1]
## par ind fam cient autor verna cap ht hc qf qc estrato
## <int> <int> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <int> <int> <chr>
## 1 3 1 Euph~ Alch~ (Spr~ Tanh~ 82 17 6 2 1 dossel
## 2 3 2 Meli~ Guar~ Vahl Café~ 18 5.5 3 1 1 sub
## 3 3 3 Laur~ Ocot~ (Nee~ Cane~ 20 6 4 2 1 sub
## 4 3 4 Elae~ Sloa~ (Aub~ Uruc~ 57 10 7 3 2 inter
## 5 3 5 Aqui~ Ilex~ Reis~ Caúna 70 12 7 3 2 dossel
## 6 3 6 Myrt~ Myrc~ (D.L~ Camb~ 17 8 3 3 3 sub
## # ... with 3 more variables: obs <chr>, dap <dbl>, g <dbl>
# A função não modifica nenhuma observação ou variável do data frameMutate
summarise()summarise() resume…
Summarise
pivot_longer()pivot_longer()